home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / LINUX / MATH_EMU.ZIP / MATH_EMU / FPU_CALC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1979-12-31  |  22.9 KB  |  817 lines

  1. /*        $NetBSD$  */
  2.  
  3. /*
  4.  * Copyright (c) 1995 Gordon W. Ross
  5.  * portion Copyright (c) 1995 Ken Nakata
  6.  * All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. The name of the author may not be used to endorse or promote products
  17.  *    derived from this software without specific prior written permission.
  18.  * 4. All advertising materials mentioning features or use of this software
  19.  *    must display the following acknowledgement:
  20.  *      This product includes software developed by Gordon Ross
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  23.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  24.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  25.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  26.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  27.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  31.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32.  */
  33.  
  34. #include "stddef.h"
  35. #include "types.h"
  36. #include "signal.h"
  37. #include "frame.h"
  38.  
  39. #include "fpu_emul.h"
  40.  
  41. /* To check for supervisor status */
  42. #define SUPER(frame) ((frame)->f_sr&0x2000)
  43.  
  44. /*
  45.  * Prototypes of static functions
  46.  */
  47. static int decode_ea6(struct frame *frame, struct instruction *insn,
  48.                                  struct insn_ea *ea, int modreg);
  49. static int fetch_immed(struct frame *frame, struct instruction *insn,
  50.                                   int *dst);
  51. static int fetch_disp(struct frame *frame, struct instruction *insn,
  52.                                  int size, int *res);
  53. static int calc_ea(struct insn_ea *ea, char *ptr, char **eaddr);
  54.  
  55. /*
  56.  * Helper routines for dealing with "effective address" values.
  57.  */
  58.  
  59. /*
  60.  * Decode an effective address into internal form.
  61.  * Returns zero on success, else signal number.
  62.  */
  63. int
  64. fpu_decode_ea(frame, insn, ea, modreg)
  65.      struct frame *frame;
  66.      struct instruction *insn;
  67.      struct insn_ea *ea;
  68.      int modreg;
  69. {
  70.     int data, sig;
  71.  
  72. #ifdef DEBUG
  73.     if (insn->is_datasize < 0) {
  74. /*          panic("decode_ea: called with uninitialized datasize\n");
  75. */    }
  76. #endif
  77.  
  78.     sig = 0;
  79.  
  80.     /* Set the most common value here. */
  81.     ea->ea_regnum = 8 + (modreg & 7);
  82.  
  83.     switch (modreg & 070) {
  84.     case 0:                             /* Dn */
  85.           ea->ea_regnum &= 7;
  86.     case 010:                           /* An */
  87.           ea->ea_flags = EA_DIRECT;
  88. #ifdef DEBUG
  89.           if (fpu_debug_level & DL_DECODEEA) {
  90.               printf("  decode_ea: register direct reg=%d\n", ea->ea_regnum);
  91.           }
  92. #endif
  93.           break;
  94.  
  95.     case 020:                           /* (An) */
  96.           ea->ea_flags = 0;
  97. #ifdef DEBUG
  98.           if (fpu_debug_level & DL_DECODEEA) {
  99.               printf("  decode_ea: register indirect reg=%d\n", ea->ea_regnum);
  100.           }
  101. #endif
  102.           break;
  103.  
  104.     case 030:                           /* (An)+ */
  105.           ea->ea_flags = EA_POSTINCR;
  106. #ifdef DEBUG
  107.           if (fpu_debug_level & DL_DECODEEA) {
  108.               printf("  decode_ea: reg indirect postincrement reg=%d\n",
  109.                        ea->ea_regnum);
  110.           }
  111. #endif
  112.           break;
  113.  
  114.     case 040:                           /* -(An) */
  115.           ea->ea_flags = EA_PREDECR;
  116. #ifdef DEBUG
  117.           if (fpu_debug_level & DL_DECODEEA) {
  118.               printf("  decode_ea: reg indirect predecrement reg=%d\n",
  119.                        ea->ea_regnum);
  120.           }
  121. #endif
  122.           break;
  123.  
  124.     case 050:                           /* (d16,An) */
  125.           ea->ea_flags = EA_OFFSET;
  126.           sig = fetch_disp(frame, insn, 1, &ea->ea_offset);
  127. #ifdef DEBUG
  128.           if (fpu_debug_level & DL_DECODEEA) {
  129.               printf("  decode_ea: reg indirect with displacement reg=%d\n",
  130.                        ea->ea_regnum);
  131.           }
  132. #endif
  133.           break;
  134.  
  135.     case 060:                           /* (d8,An,Xn) */
  136.           ea->ea_flags = EA_INDEXED;
  137.           sig = decode_ea6(frame, insn, ea, modreg);
  138.           break;
  139.  
  140.     case 070:                           /* misc. */
  141.           ea->ea_regnum = (modreg & 7);
  142.           switch (modreg & 7) {
  143.  
  144.           case 0:                       /* (xxxx).W */
  145.               ea->ea_flags = EA_ABS;
  146.               sig = fetch_disp(frame, insn, 1, &ea->ea_absaddr);
  147. #ifdef DEBUG
  148.               if (fpu_debug_level & DL_DECODEEA) {
  149.                     printf("  decode_ea: absolute address (word)\n");
  150.               }
  151. #endif
  152.               break;
  153.  
  154.           case 1:                       /* (xxxxxxxx).L */
  155.               ea->ea_flags = EA_ABS;
  156.               sig = fetch_disp(frame, insn, 2, &ea->ea_absaddr);
  157. #ifdef DEBUG
  158.               if (fpu_debug_level & DL_DECODEEA) {
  159.                     printf("  decode_ea: absolute address (long)\n");
  160.               }
  161. #endif
  162.               break;
  163.  
  164.           case 2:                       /* (d16,PC) */
  165.               ea->ea_flags = EA_PC_REL | EA_OFFSET;
  166.               sig = fetch_disp(frame, insn, 1, &ea->ea_absaddr);
  167. #ifdef DEBUG
  168.               if (fpu_debug_level & DL_DECODEEA) {
  169.                     printf("  decode_ea: pc relative word displacement\n");
  170.               }
  171. #endif
  172.               break;
  173.  
  174.           case 3:                       /* (d8,PC,Xn) */
  175.               ea->ea_flags = EA_PC_REL | EA_INDEXED;
  176.               sig = decode_ea6(frame, insn, ea, modreg);
  177.               break;
  178.  
  179.           case 4:                       /* #data */
  180.               ea->ea_flags = EA_IMMED;
  181.               sig = fetch_immed(frame, insn, &ea->ea_immed[0]);
  182. #ifdef DEBUG
  183.               if (fpu_debug_level & DL_DECODEEA) {
  184.                     printf("  decode_ea: immediate size=%d\n", insn->is_datasize);
  185.               }
  186. #endif
  187.               break;
  188.  
  189.           default:
  190. #ifdef DEBUG
  191.               if (fpu_debug_level & DL_DECODEEA) {
  192.                     printf("  decode_ea: invalid addr mode (7,%d)\n", modreg & 7);
  193.               }
  194. #endif
  195.               return SIGILL;
  196.           } /* switch for mode 7 */
  197.           break;
  198.     } /* switch mode */
  199.  
  200.     ea->ea_tdisp = 0;
  201.  
  202.     return sig;
  203. }
  204.  
  205. /*
  206.  * Decode Mode=6 address modes
  207.  */
  208. static int
  209. decode_ea6(frame, insn, ea, modreg)
  210.      struct frame *frame;
  211.      struct instruction *insn;
  212.      struct insn_ea *ea;
  213.      int modreg;
  214. {
  215.     int word, extword, idx;
  216.     int basedisp, outerdisp;
  217.     int bd_size, od_size;
  218.     int sig;
  219.  
  220.     extword = fusword(frame->f_pc + insn->is_advance);
  221.     if (extword < 0) {
  222.           return SIGSEGV;
  223.     }
  224.     insn->is_advance += 2;
  225.  
  226.     /* get register index */
  227.     ea->ea_idxreg = (extword >> 12) & 0xf;
  228.     idx = frame->f_regs[ea->ea_idxreg];
  229.     if ((extword & 0x0800) == 0) {
  230.           /* if word sized index, sign-extend */
  231.           idx &= 0xffff;
  232.           if (idx & 0x8000) {
  233.               idx |= 0xffff0000;
  234.           }
  235.     }
  236.     /* scale register index */
  237.     idx <<= ((extword >>9) & 3);
  238.  
  239.     if ((extword & 0x100) == 0) {
  240.           /* brief extention word - sign-extend the displacement */
  241.           basedisp = (extword & 0xff);
  242.           if (basedisp & 0x80) {
  243.               basedisp |= 0xffffff00;
  244.           }
  245.  
  246.           ea->ea_basedisp = idx + basedisp;
  247.           ea->ea_outerdisp = 0;
  248. #ifdef DEBUG
  249.           if (fpu_debug_level & DL_DECODEEA) {
  250.               printf("  decode_ea6: brief ext word idxreg=%d, basedisp=%08x\n",
  251.                        ea->ea_idxreg, ea->ea_basedisp);
  252.           }
  253. #endif
  254.     } else {
  255.           /* full extention word */
  256.           if (extword & 0x80) {
  257.               ea->ea_flags |= EA_BASE_SUPPRSS;
  258.           }
  259.           bd_size = ((extword >> 4) & 3) - 1;
  260.           od_size = (extword & 3) - 1;
  261.           sig = fetch_disp(frame, insn, bd_size, &basedisp);
  262.           if (sig) {
  263.               return sig;
  264.           }
  265.           if (od_size >= 0) {
  266.               ea->ea_flags |= EA_MEM_INDIR;
  267.           }
  268.           sig = fetch_disp(frame, insn, od_size, &outerdisp);
  269.           if (sig) {
  270.               return sig;
  271.           }
  272.  
  273.           switch (extword & 0x44) {
  274.           case 0:                       /* preindexed */
  275.               ea->ea_basedisp = basedisp + idx;
  276.               ea->ea_outerdisp = outerdisp;
  277.               break;
  278.           case 4:                       /* postindexed */
  279.               ea->ea_basedisp = basedisp;
  280.               ea->ea_outerdisp = outerdisp + idx;
  281.               break;
  282.           case 0x40:                    /* no index */
  283.               ea->ea_basedisp = basedisp;
  284.               ea->ea_outerdisp = outerdisp;
  285.               break;
  286.           default:
  287. #ifdef DEBUG
  288.               printf("  decode_ea6: invalid indirect mode: ext word %04x\n",
  289.                        extword);
  290. #endif
  291.               return SIGILL;
  292.               break;
  293.           }
  294. #ifdef DEBUG
  295.           if (fpu_debug_level & DL_DECODEEA) {
  296.               printf("  decode_ea6: full ext idxreg=%d, basedisp=%x, outerdisp=%x\n",
  297.                        ea->ea_idxreg, ea->ea_basedisp, ea->ea_outerdisp);
  298.           }
  299. #endif
  300.     }
  301. #ifdef DEBUG
  302.     if (fpu_debug_level & DL_DECODEEA) {
  303.           printf("  decode_ea6: regnum=%d, flags=%x\n",
  304.                  ea->ea_regnum, ea->ea_flags);
  305.     }
  306. #endif
  307.     return 0;
  308. }
  309.  
  310. /*
  311.  * Load a value from an effective address.
  312.  * Returns zero on success, else signal number.
  313.  */
  314. int
  315. fpu_load_ea(frame, insn, ea, dst)
  316.      struct frame *frame;
  317.      struct instruction *insn;
  318.      struct insn_ea *ea;
  319.      char *dst;
  320. {
  321.     int *reg;
  322.     char *src;
  323.     int len, step;
  324.     int data, word, sig;
  325.  
  326. #ifdef    DIAGNOSTIC
  327.     if (ea->ea_regnum & ~0xF) {
  328.           panic("  load_ea: bad regnum");
  329.     }
  330. #endif
  331. #ifdef DEBUG
  332.     if (fpu_debug_level & DL_LOADEA) {
  333.           printf("  load_ea: frame at %08x\n", frame);
  334.     }
  335. #endif
  336.     /* The dst is always int or larger. */
  337.     len = insn->is_datasize;
  338.     if (len < 4) {
  339.           dst += (4 - len);
  340.     }
  341.     step = (len == 1 && ea->ea_regnum == 15 /* sp */) ? 2 : len;
  342.  
  343.     if (ea->ea_flags & EA_DIRECT) {
  344.           if (len > 4) {
  345. #ifdef DEBUG
  346.               printf("  load_ea: operand doesn't fit cpu reg\n");
  347. #endif
  348.               return SIGILL;
  349.           }
  350.           if (ea->ea_tdisp > 0) {
  351. #ifdef DEBUG
  352.               printf("  load_ea: more than one move from cpu reg\n");
  353. #endif
  354.               return SIGILL;
  355.           }
  356.           src = (char *)&frame->f_regs[ea->ea_regnum];
  357.           /* The source is an int. */
  358.           if (len < 4) {
  359.               src += (4 - len);
  360. #ifdef DEBUG
  361.               if (fpu_debug_level & DL_LOADEA) {
  362.                     printf("  load_ea: short/byte opr - addr adjusted\n");
  363.               }
  364. #endif
  365.           }
  366. #ifdef DEBUG
  367.           if (fpu_debug_level & DL_LOADEA) {
  368.               printf("  load_ea: src 0x%08x\n", src);
  369.           }
  370. #endif
  371.           fpu_copy(src, dst, len);
  372.     } else if (ea->ea_flags & EA_IMMED) {
  373. #ifdef DEBUG
  374.           if (fpu_debug_level & DL_LOADEA) {
  375.               printf("  load_ea: immed %08x%08x%08x size %d\n",
  376.                        ea->ea_immed[0], ea->ea_immed[1], ea->ea_immed[2], len);
  377.           }
  378. #endif
  379.           src = (char *)&ea->ea_immed[0];
  380.           if (len < 4) {
  381.               src += (4 - len);
  382. #ifdef DEBUG
  383.               if (fpu_debug_level & DL_LOADEA) {
  384.                     printf("  load_ea: short/byte immed opr - addr adjusted\n");
  385.               }
  386. #endif
  387.           }
  388.           fpu_copy(src, dst, len);
  389.     } else if (ea->ea_flags & EA_ABS) {
  390. #ifdef DEBUG
  391.           if (fpu_debug_level & DL_LOADEA) {
  392.               printf("  load_ea: abs addr %08x\n", ea->ea_absaddr);
  393.           }
  394. #endif
  395.           src = (char *)ea->ea_absaddr;
  396.           
  397.  
  398.  
  399.       if(SUPER(frame)) { 
  400.                    fpu_copy(src, dst, len);
  401.           } else {
  402.               copyin(src, dst, len);
  403.           }
  404.  
  405.  
  406.  
  407.  
  408.     } else /* register indirect */ { 
  409.           if (ea->ea_flags & EA_PC_REL) {
  410. #ifdef DEBUG
  411.               if (fpu_debug_level & DL_LOADEA) {
  412.                     printf("  load_ea: using PC\n");
  413.               }
  414. #endif
  415.               reg = NULL;
  416.               /* Grab the register contents. 4 is offset to the first
  417.                  extention word from the opcode */
  418.               src = (char *)frame->f_pc + 4;
  419. #ifdef DEBUG
  420.               if (fpu_debug_level & DL_LOADEA) {
  421.                     printf("  load_ea: pc relative pc+4 = 0x%08x\n", src);
  422.               }
  423. #endif
  424.           } else /* not PC relative */ {
  425. #ifdef DEBUG
  426.               if (fpu_debug_level & DL_LOADEA) {
  427.                     printf("  load_ea: using register %c%d\n",
  428.                            (ea->ea_regnum >= 8) ? 'a' : 'd', ea->ea_regnum & 7);
  429.               }
  430. #endif
  431.               /* point to the register */
  432.               reg = &frame->f_regs[ea->ea_regnum];
  433.  
  434.               if (ea->ea_flags & EA_PREDECR) {
  435. #ifdef DEBUG
  436.                     if (fpu_debug_level & DL_LOADEA) {
  437.                         printf("  load_ea: predecr mode - reg decremented\n");
  438.                     }
  439. #endif
  440.                     *reg -= step;
  441.                     ea->ea_tdisp = 0;
  442.               }
  443.  
  444.               /* Grab the register contents. */
  445.               src = (char *)*reg;
  446. #ifdef DEBUG
  447.               if (fpu_debug_level & DL_LOADEA) {
  448.                     printf("  load_ea: reg indirect reg = 0x%08x\n", src);
  449.               }
  450. #endif
  451.           }
  452.  
  453.           sig = calc_ea(ea, src, &src);
  454.           if (sig)
  455.               return sig;
  456.  
  457.           
  458.           if(SUPER(frame)) {
  459.               fpu_copy(src + ea->ea_tdisp, dst, len);
  460.           } else {
  461.               copyin(src + ea->ea_tdisp, dst, len);
  462.           }
  463.           
  464.           
  465.           /* do post-increment */
  466.           if (ea->ea_flags & EA_POSTINCR) {
  467.               if (ea->ea_flags & EA_PC_REL) {
  468. #ifdef DEBUG
  469.                     printf("  load_ea: tried to postincrement PC\n");
  470. #endif
  471.                     return SIGILL;
  472.               }
  473.               *reg += step;
  474.               ea->ea_tdisp = 0;
  475. #ifdef DEBUG
  476.               if (fpu_debug_level & DL_LOADEA) {
  477.                     printf("  load_ea: postinc mode - reg incremented\n");
  478.               }
  479. #endif
  480.           } else {
  481.               ea->ea_tdisp += len;
  482.           }
  483.     }
  484.  
  485.     return 0;
  486. }
  487.  
  488. /*
  489.  * Store a value at the effective address.
  490.  * Returns zero on success, else signal number.
  491.  */
  492. int
  493. fpu_store_ea(frame, insn, ea, src)
  494.      struct frame *frame;
  495.      struct instruction *insn;
  496.      struct insn_ea *ea;
  497.      char *src;
  498. {
  499.     int *reg;
  500.     char *dst;
  501.     int len, step;
  502.     int data, word, sig;
  503.  
  504. #ifdef    DIAGNOSTIC
  505.     if (ea->ea_regnum & ~0xF) {
  506.           panic("  store_ea: bad regnum");
  507.     }
  508. #endif
  509.  
  510.     if (ea->ea_flags & (EA_IMMED|EA_PC_REL)) {
  511.           /* not alterable address mode */
  512. #ifdef DEBUG
  513.           printf("  store_ea: not alterable address mode\n");
  514. #endif
  515.           return SIGILL;
  516.     }
  517. #ifdef DEBUG
  518.     if (fpu_debug_level & DL_STOREEA) {
  519.           printf("  store_ea: frame at %08x\n", frame);
  520.     }
  521. #endif
  522.     /* The src is always int or larger. */
  523.     len = insn->is_datasize;
  524.     if (len < 4) {
  525.           src += (4 - len);
  526.     }
  527.     step = (len == 1 && ea->ea_regnum == 15 /* sp */) ? 2 : len;
  528.  
  529.     if (ea->ea_flags & EA_ABS) {
  530. #ifdef DEBUG
  531.           if (fpu_debug_level & DL_STOREEA) {
  532.               printf("  store_ea: abs addr %08x\n", ea->ea_absaddr);
  533.           }
  534. #endif
  535.           dst = (char *)ea->ea_absaddr;
  536.           
  537.  
  538.           
  539.           if(SUPER(frame)) {
  540.               fpu_copy(src, dst + ea->ea_tdisp, len);
  541.           } else {
  542.               copyout(src, dst + ea->ea_tdisp, len);
  543.           }
  544.                     
  545.           
  546.           ea->ea_tdisp += len;
  547.     } else if (ea->ea_flags & EA_DIRECT) {
  548.           if (len > 4) {
  549. #ifdef DEBUG
  550.               printf("  store_ea: operand doesn't fit cpu reg\n");
  551. #endif
  552.               return SIGILL;
  553.           }
  554.           if (ea->ea_tdisp > 0) {
  555. #ifdef DEBUG
  556.               printf("  store_ea: more than one move to cpu reg\n");
  557. #endif
  558.               return SIGILL;
  559.           }
  560.           dst = (char*)&frame->f_regs[ea->ea_regnum];
  561.           /* The destination is an int. */
  562.           if (len < 4) {
  563.               dst += (4 - len);
  564. #ifdef DEBUG
  565.               if (fpu_debug_level & DL_STOREEA) {
  566.                     printf("  store_ea: short/byte opr - dst addr adjusted\n");
  567.               }
  568. #endif
  569.           }
  570. #ifdef DEBUG
  571.           if (fpu_debug_level & DL_STOREEA) {
  572.               printf("  store_ea: dst 0x%08x\n", dst);
  573.           }
  574. #endif
  575.           fpu_copy(src, dst, len);
  576.     } else /* One of MANY indirect forms... */ {
  577. #ifdef DEBUG
  578.           if (fpu_debug_level & DL_STOREEA) {
  579.               printf("  store_ea: using register %c%d\n",
  580.                        (ea->ea_regnum >= 8) ? 'a' : 'd', ea->ea_regnum & 7);
  581.           }
  582. #endif
  583.           /* point to the register */
  584.           reg = &(frame->f_regs[ea->ea_regnum]);
  585.  
  586.           /* do pre-decrement */
  587.           if (ea->ea_flags & EA_PREDECR) {
  588. #ifdef DEBUG
  589.               if (fpu_debug_level & DL_STOREEA) {
  590.                     printf("  store_ea: predecr mode - reg decremented\n");
  591.               }
  592. #endif
  593.               *reg -= step;
  594.               ea->ea_tdisp = 0;
  595.           }
  596.  
  597.           /* calculate the effective address */
  598.           sig = calc_ea(ea, (char *)*reg, &dst);
  599.           if (sig)
  600.               return sig;
  601. #ifdef DEBUG
  602.           if (fpu_debug_level & DL_STOREEA) {
  603.               printf("  store_ea: dst addr=0x%08x+%d\n", dst, ea->ea_tdisp);
  604.           }
  605. #endif
  606.           
  607.           
  608.           if(SUPER(frame)) {
  609.               fpu_copy(src, dst + ea->ea_tdisp, len);
  610.           } else {
  611.               copyout(src, dst + ea->ea_tdisp, len);
  612.           }
  613.  
  614.  
  615.           /* do post-increment */
  616.           if (ea->ea_flags & EA_POSTINCR) {
  617.               *reg += step;
  618.               ea->ea_tdisp = 0;
  619. #ifdef DEBUG
  620.               if (fpu_debug_level & DL_STOREEA) {
  621.                     printf("  store_ea: postinc mode - reg incremented\n");
  622.               }
  623. #endif
  624.           } else {
  625.               ea->ea_tdisp += len;
  626.           }
  627.     }
  628.  
  629.     return 0;
  630. }
  631.  
  632. /*
  633.  * fetch_immed: fetch immediate operand
  634.  */
  635. static int
  636. fetch_immed(frame, insn, dst)
  637.      struct frame *frame;
  638.      struct instruction *insn;
  639.      int *dst;
  640. {
  641.     int data, ext_bytes;
  642.  
  643.     ext_bytes = insn->is_datasize;
  644.  
  645.     if (0 < ext_bytes) {
  646.           data = fusword(frame->f_pc + insn->is_advance);
  647.           if (data < 0) {
  648.               return SIGSEGV;
  649.           }
  650.           if (ext_bytes == 1) {
  651.               /* sign-extend byte to long */
  652.               data &= 0xff;
  653.               if (data & 0x80) {
  654.                     data |= 0xffffff00;
  655.               }
  656.           } else if (ext_bytes == 2) {
  657.               /* sign-extend word to long */
  658.               data &= 0xffff;
  659.               if (data & 0x8000) {
  660.                     data |= 0xffff0000;
  661.               }
  662.           }
  663.           insn->is_advance += 2;
  664.           dst[0] = data;
  665.     }
  666.     if (2 < ext_bytes) {
  667.           data = fusword(frame->f_pc + insn->is_advance);
  668.           if (data < 0) {
  669.               return SIGSEGV;
  670.           }
  671.           insn->is_advance += 2;
  672.           dst[0] <<= 16;
  673.           dst[0] |= data;
  674.     }
  675.     if (4 < ext_bytes) {
  676.           data = fusword(frame->f_pc + insn->is_advance);
  677.           if (data < 0) {
  678.               return SIGSEGV;
  679.           }
  680.           dst[1] = data << 16;
  681.           data = fusword(frame->f_pc + insn->is_advance + 2);
  682.           if (data < 0) {
  683.               return SIGSEGV;
  684.           }
  685.           insn->is_advance += 4;
  686.           dst[1] |= data;
  687.     }
  688.     if (8 < ext_bytes) {
  689.           data = fusword(frame->f_pc + insn->is_advance);
  690.           if (data < 0) {
  691.               return SIGSEGV;
  692.           }
  693.           dst[2] = data << 16;
  694.           data = fusword(frame->f_pc + insn->is_advance + 2);
  695.           if (data < 0) {
  696.               return SIGSEGV;
  697.           }
  698.           insn->is_advance += 4;
  699.           dst[2] |= data;
  700.     }
  701.  
  702.     return 0;
  703. }
  704.  
  705. /*
  706.  * fetch_disp: fetch displacement in full extention words
  707.  */
  708. static int
  709. fetch_disp(frame, insn, size, res)
  710.      struct frame *frame;
  711.      struct instruction *insn;
  712.      int size, *res;
  713. {
  714.     int disp, word;
  715.  
  716.     if (size == 1) {
  717.           word = fusword(frame->f_pc + insn->is_advance);
  718.           if (word < 0) {
  719.               return SIGSEGV;
  720.           }
  721.           disp = word & 0xffff;
  722.           if (disp & 0x8000) {
  723.               /* sign-extend */
  724.               disp |= 0xffff0000;
  725.           }
  726.           insn->is_advance += 2;
  727.     } else if (size == 2) {
  728.           word = fusword(frame->f_pc + insn->is_advance);
  729.           if (word < 0) {
  730.               return SIGSEGV;
  731.           }
  732.           disp = word << 16;
  733.           word = fusword(frame->f_pc + insn->is_advance + 2);
  734.           if (word < 0) {
  735.               return SIGSEGV;
  736.           }
  737.           disp |= (word & 0xffff);
  738.           insn->is_advance += 4;
  739.     } else {
  740.           disp = 0;
  741.     }
  742.     *res = disp;
  743.     return 0;
  744. }
  745.  
  746. /*
  747.  * Calculates an effective address for all address modes except for
  748.  * register direct, absolute, and immediate modes.  However, it does
  749.  * not take care of predecrement/postincrement of register content.
  750.  * Returns a signal value (0 == no error).
  751.  */
  752. static int
  753. calc_ea(ea, ptr, eaddr)
  754.      struct insn_ea *ea;
  755.      char *ptr;               /* base address (usually a register content) */
  756.      char **eaddr;  /* pointer to result pointer */
  757. {
  758.     int data, word, sig;
  759. #ifdef DEBUG
  760.     if (fpu_debug_level & DL_EA) {
  761.           printf("  calc_ea: reg indirect (reg) = 0x%08x\n", ptr);
  762.     }
  763. #endif
  764.     if (ea->ea_flags & EA_OFFSET) {
  765.           /* apply the signed offset */
  766. #ifdef DEBUG
  767.           if (fpu_debug_level & DL_EA) {
  768.               printf("  calc_ea: offset %d\n", ea->ea_offset);
  769.           }
  770. #endif
  771.           ptr += ea->ea_offset;
  772.     } else if (ea->ea_flags & EA_INDEXED) {
  773. #ifdef DEBUG
  774.           if (fpu_debug_level & DL_EA) {
  775.               printf("  calc_ea: indexed mode\n");
  776.           }
  777. #endif
  778.           if (ea->ea_flags & EA_BASE_SUPPRSS) {
  779.               /* base register is suppressed */
  780.               ptr = (char *)ea->ea_basedisp;
  781.           } else {
  782.               ptr += ea->ea_basedisp;
  783.           }
  784.  
  785.           if (ea->ea_flags & EA_MEM_INDIR) {
  786. #ifdef DEBUG
  787.               if (fpu_debug_level & DL_EA) {
  788.                     printf("  calc_ea: mem indir mode: basedisp=%08x, outerdisp=%08x\n",
  789.                            ea->ea_basedisp, ea->ea_outerdisp);
  790.                     printf("  calc_ea: addr fetched from 0x%08x\n", ptr);
  791.               }
  792. #endif
  793.               /* memory indirect modes */
  794.               word = fusword(ptr);
  795.               if (word < 0) {
  796.                     return SIGSEGV;
  797.               }
  798.               word <<= 16;
  799.               data = fusword(ptr + 2);
  800.               if (data < 0) {
  801.                     return SIGSEGV;
  802.               }
  803.               word |= data;
  804. #ifdef DEBUG
  805.               if (fpu_debug_level & DL_STOREEA) {
  806.                     printf(" calc_ea: fetched ptr 0x%08x\n", word);
  807.               }
  808. #endif
  809.               ptr = (char *)word + ea->ea_outerdisp;
  810.           }
  811.     }
  812.  
  813.     *eaddr = ptr;
  814.  
  815.     return 0;
  816. }
  817.